const std = @import("std");
const assert = std.debug.assert;
const net = @import("../net.zig");
const NetBitOrder = net.NetBitOrder;
const Udp = net.udp.Udp;

/// an DNS packet (comes after an UDP header).
pub const Dns = extern struct {
    /// request ID
    id: u16 align(1),
    flags: NetBitOrder(Flags) align(1),

    /// number of question entries
    qd_count: u16 align(1),
    /// number of resource records in answer section
    an_count: u16 align(1),
    /// number of NS resource records in authority section
    ns_count: u16 align(1),
    /// number of resource records in additional records
    ar_count: u16 align(1),

    pub const Flags = packed struct(u16) {
        /// query/response
        qr: bool,
        opcode: u4,
        /// authoritive
        aa: bool,
        /// truncated
        tc: bool,
        /// recursion desired
        rd: bool,

        /// recursion available
        ra: bool,
        z: bool,
        /// authenticated data
        ad: bool,
        /// checking disabled
        cd: bool,
        /// response code
        rcode: u4,
    };

    pub const Question = packed struct {
        type: u16,
        class: u16,
    };

    pub const Data = packed struct {
        type: u16,
        class: u16,
        ttl: u32,
        len: u16,
    };

    comptime {
        assert(@alignOf(@This()) == 1);
        assert(@bitSizeOf(@This()) / 8 == @sizeOf(@This()));
    }

    pub const header_size = @sizeOf(@This());
    pub const packet_lenth = Udp.packet_lenth + header_size;
};
